Get widgets working on the btree/buffer side. Display of them still
authorHavoc Pennington <hp@redhat.com>
Fri, 3 Nov 2000 20:40:57 +0000 (20:40 +0000)
committerHavoc Pennington <hp@src.gnome.org>
Fri, 3 Nov 2000 20:40:57 +0000 (20:40 +0000)
2000-11-03  Havoc Pennington  <hp@redhat.com>

        Get widgets working on the btree/buffer side. Display of them
still doesn't work.

* gtk/gtktextview.c: start implementing child widget stuff

* gtk/gtktextiter.c (gtk_text_iter_get_child_anchor): new function

* gtk/gtktextlayout.c: handle embedded widgets

* gtk/gtktextdisplay.c: handle embedded widgets

* gtk/gtktextchild.c: Implement all the child anchor goo

* gtk/gtktextbuffer.c (gtk_text_buffer_create_child_anchor): New
function

* gtk/gtktextbtree.c: Add child anchor table to the btree struct
(insert_pixbuf_or_widget_segment): abstract out common portions of
creating a child anchor or a pixbuf segment.
(gtk_text_btree_create_child_anchor): new function
(gtk_text_btree_unregister_child_anchor): new function

* gtk/gtkmarshal.list: added VOID:OBJECT,INT,INT for the
allocate_child signal on GtkTextLayout

* gtk/gtktextiter.c (gtk_text_iter_get_pixbuf): fix bogus return
values
(gtk_text_iter_get_child_anchor): new function

* gtk/gtktextbuffer.c (gtk_text_buffer_real_changed): Add a
default handler for the changed signal, which calls
gtk_text_buffer_set_modified(), instead of just always emitting
changed then calling set_modified() manually. I guess this is
maybe more flexible. It seems logical.

22 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gtk/gtkmarshal.list
gtk/gtkmarshalers.list
gtk/gtktextbtree.c
gtk/gtktextbtree.h
gtk/gtktextbuffer.c
gtk/gtktextbuffer.h
gtk/gtktextchild.c
gtk/gtktextchild.h
gtk/gtktextchildprivate.h
gtk/gtktextdisplay.c
gtk/gtktextiter.c
gtk/gtktextiter.h
gtk/gtktextlayout.c
gtk/gtktextlayout.h
gtk/gtktextview.c

index cde1f062e0a503b307ef349cf6b8eb59203d62b3..aa193e9b6c76f02b0866674b86b902d6b0810cef 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,40 @@
+2000-11-03  Havoc Pennington  <hp@redhat.com>
+
+        Get widgets working on the btree/buffer side. Display of them 
+       still doesn't work.
+       
+       * gtk/gtktextview.c: start implementing child widget stuff
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_child_anchor): new function
+
+       * gtk/gtktextlayout.c: handle embedded widgets
+
+       * gtk/gtktextdisplay.c: handle embedded widgets
+
+       * gtk/gtktextchild.c: Implement all the child anchor goo
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_create_child_anchor): New
+       function
+
+       * gtk/gtktextbtree.c: Add child anchor table to the btree struct
+       (insert_pixbuf_or_widget_segment): abstract out common portions of 
+       creating a child anchor or a pixbuf segment.
+       (gtk_text_btree_create_child_anchor): new function
+       (gtk_text_btree_unregister_child_anchor): new function
+
+       * gtk/gtkmarshal.list: added VOID:OBJECT,INT,INT for the
+       allocate_child signal on GtkTextLayout
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_pixbuf): fix bogus return
+       values
+       (gtk_text_iter_get_child_anchor): new function
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_real_changed): Add a
+       default handler for the changed signal, which calls
+       gtk_text_buffer_set_modified(), instead of just always emitting
+       changed then calling set_modified() manually. I guess this is
+       maybe more flexible. It seems logical.
+
 Fri Nov  3 08:58:38 2000  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkobject.c: _g_signal_handlers_destroy() is prefixed with '_'
index cde1f062e0a503b307ef349cf6b8eb59203d62b3..aa193e9b6c76f02b0866674b86b902d6b0810cef 100644 (file)
@@ -1,3 +1,40 @@
+2000-11-03  Havoc Pennington  <hp@redhat.com>
+
+        Get widgets working on the btree/buffer side. Display of them 
+       still doesn't work.
+       
+       * gtk/gtktextview.c: start implementing child widget stuff
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_child_anchor): new function
+
+       * gtk/gtktextlayout.c: handle embedded widgets
+
+       * gtk/gtktextdisplay.c: handle embedded widgets
+
+       * gtk/gtktextchild.c: Implement all the child anchor goo
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_create_child_anchor): New
+       function
+
+       * gtk/gtktextbtree.c: Add child anchor table to the btree struct
+       (insert_pixbuf_or_widget_segment): abstract out common portions of 
+       creating a child anchor or a pixbuf segment.
+       (gtk_text_btree_create_child_anchor): new function
+       (gtk_text_btree_unregister_child_anchor): new function
+
+       * gtk/gtkmarshal.list: added VOID:OBJECT,INT,INT for the
+       allocate_child signal on GtkTextLayout
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_pixbuf): fix bogus return
+       values
+       (gtk_text_iter_get_child_anchor): new function
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_real_changed): Add a
+       default handler for the changed signal, which calls
+       gtk_text_buffer_set_modified(), instead of just always emitting
+       changed then calling set_modified() manually. I guess this is
+       maybe more flexible. It seems logical.
+
 Fri Nov  3 08:58:38 2000  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkobject.c: _g_signal_handlers_destroy() is prefixed with '_'
index cde1f062e0a503b307ef349cf6b8eb59203d62b3..aa193e9b6c76f02b0866674b86b902d6b0810cef 100644 (file)
@@ -1,3 +1,40 @@
+2000-11-03  Havoc Pennington  <hp@redhat.com>
+
+        Get widgets working on the btree/buffer side. Display of them 
+       still doesn't work.
+       
+       * gtk/gtktextview.c: start implementing child widget stuff
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_child_anchor): new function
+
+       * gtk/gtktextlayout.c: handle embedded widgets
+
+       * gtk/gtktextdisplay.c: handle embedded widgets
+
+       * gtk/gtktextchild.c: Implement all the child anchor goo
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_create_child_anchor): New
+       function
+
+       * gtk/gtktextbtree.c: Add child anchor table to the btree struct
+       (insert_pixbuf_or_widget_segment): abstract out common portions of 
+       creating a child anchor or a pixbuf segment.
+       (gtk_text_btree_create_child_anchor): new function
+       (gtk_text_btree_unregister_child_anchor): new function
+
+       * gtk/gtkmarshal.list: added VOID:OBJECT,INT,INT for the
+       allocate_child signal on GtkTextLayout
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_pixbuf): fix bogus return
+       values
+       (gtk_text_iter_get_child_anchor): new function
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_real_changed): Add a
+       default handler for the changed signal, which calls
+       gtk_text_buffer_set_modified(), instead of just always emitting
+       changed then calling set_modified() manually. I guess this is
+       maybe more flexible. It seems logical.
+
 Fri Nov  3 08:58:38 2000  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkobject.c: _g_signal_handlers_destroy() is prefixed with '_'
index cde1f062e0a503b307ef349cf6b8eb59203d62b3..aa193e9b6c76f02b0866674b86b902d6b0810cef 100644 (file)
@@ -1,3 +1,40 @@
+2000-11-03  Havoc Pennington  <hp@redhat.com>
+
+        Get widgets working on the btree/buffer side. Display of them 
+       still doesn't work.
+       
+       * gtk/gtktextview.c: start implementing child widget stuff
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_child_anchor): new function
+
+       * gtk/gtktextlayout.c: handle embedded widgets
+
+       * gtk/gtktextdisplay.c: handle embedded widgets
+
+       * gtk/gtktextchild.c: Implement all the child anchor goo
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_create_child_anchor): New
+       function
+
+       * gtk/gtktextbtree.c: Add child anchor table to the btree struct
+       (insert_pixbuf_or_widget_segment): abstract out common portions of 
+       creating a child anchor or a pixbuf segment.
+       (gtk_text_btree_create_child_anchor): new function
+       (gtk_text_btree_unregister_child_anchor): new function
+
+       * gtk/gtkmarshal.list: added VOID:OBJECT,INT,INT for the
+       allocate_child signal on GtkTextLayout
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_pixbuf): fix bogus return
+       values
+       (gtk_text_iter_get_child_anchor): new function
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_real_changed): Add a
+       default handler for the changed signal, which calls
+       gtk_text_buffer_set_modified(), instead of just always emitting
+       changed then calling set_modified() manually. I guess this is
+       maybe more flexible. It seems logical.
+
 Fri Nov  3 08:58:38 2000  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkobject.c: _g_signal_handlers_destroy() is prefixed with '_'
index cde1f062e0a503b307ef349cf6b8eb59203d62b3..aa193e9b6c76f02b0866674b86b902d6b0810cef 100644 (file)
@@ -1,3 +1,40 @@
+2000-11-03  Havoc Pennington  <hp@redhat.com>
+
+        Get widgets working on the btree/buffer side. Display of them 
+       still doesn't work.
+       
+       * gtk/gtktextview.c: start implementing child widget stuff
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_child_anchor): new function
+
+       * gtk/gtktextlayout.c: handle embedded widgets
+
+       * gtk/gtktextdisplay.c: handle embedded widgets
+
+       * gtk/gtktextchild.c: Implement all the child anchor goo
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_create_child_anchor): New
+       function
+
+       * gtk/gtktextbtree.c: Add child anchor table to the btree struct
+       (insert_pixbuf_or_widget_segment): abstract out common portions of 
+       creating a child anchor or a pixbuf segment.
+       (gtk_text_btree_create_child_anchor): new function
+       (gtk_text_btree_unregister_child_anchor): new function
+
+       * gtk/gtkmarshal.list: added VOID:OBJECT,INT,INT for the
+       allocate_child signal on GtkTextLayout
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_pixbuf): fix bogus return
+       values
+       (gtk_text_iter_get_child_anchor): new function
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_real_changed): Add a
+       default handler for the changed signal, which calls
+       gtk_text_buffer_set_modified(), instead of just always emitting
+       changed then calling set_modified() manually. I guess this is
+       maybe more flexible. It seems logical.
+
 Fri Nov  3 08:58:38 2000  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkobject.c: _g_signal_handlers_destroy() is prefixed with '_'
index cde1f062e0a503b307ef349cf6b8eb59203d62b3..aa193e9b6c76f02b0866674b86b902d6b0810cef 100644 (file)
@@ -1,3 +1,40 @@
+2000-11-03  Havoc Pennington  <hp@redhat.com>
+
+        Get widgets working on the btree/buffer side. Display of them 
+       still doesn't work.
+       
+       * gtk/gtktextview.c: start implementing child widget stuff
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_child_anchor): new function
+
+       * gtk/gtktextlayout.c: handle embedded widgets
+
+       * gtk/gtktextdisplay.c: handle embedded widgets
+
+       * gtk/gtktextchild.c: Implement all the child anchor goo
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_create_child_anchor): New
+       function
+
+       * gtk/gtktextbtree.c: Add child anchor table to the btree struct
+       (insert_pixbuf_or_widget_segment): abstract out common portions of 
+       creating a child anchor or a pixbuf segment.
+       (gtk_text_btree_create_child_anchor): new function
+       (gtk_text_btree_unregister_child_anchor): new function
+
+       * gtk/gtkmarshal.list: added VOID:OBJECT,INT,INT for the
+       allocate_child signal on GtkTextLayout
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_pixbuf): fix bogus return
+       values
+       (gtk_text_iter_get_child_anchor): new function
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_real_changed): Add a
+       default handler for the changed signal, which calls
+       gtk_text_buffer_set_modified(), instead of just always emitting
+       changed then calling set_modified() manually. I guess this is
+       maybe more flexible. It seems logical.
+
 Fri Nov  3 08:58:38 2000  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkobject.c: _g_signal_handlers_destroy() is prefixed with '_'
index cde1f062e0a503b307ef349cf6b8eb59203d62b3..aa193e9b6c76f02b0866674b86b902d6b0810cef 100644 (file)
@@ -1,3 +1,40 @@
+2000-11-03  Havoc Pennington  <hp@redhat.com>
+
+        Get widgets working on the btree/buffer side. Display of them 
+       still doesn't work.
+       
+       * gtk/gtktextview.c: start implementing child widget stuff
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_child_anchor): new function
+
+       * gtk/gtktextlayout.c: handle embedded widgets
+
+       * gtk/gtktextdisplay.c: handle embedded widgets
+
+       * gtk/gtktextchild.c: Implement all the child anchor goo
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_create_child_anchor): New
+       function
+
+       * gtk/gtktextbtree.c: Add child anchor table to the btree struct
+       (insert_pixbuf_or_widget_segment): abstract out common portions of 
+       creating a child anchor or a pixbuf segment.
+       (gtk_text_btree_create_child_anchor): new function
+       (gtk_text_btree_unregister_child_anchor): new function
+
+       * gtk/gtkmarshal.list: added VOID:OBJECT,INT,INT for the
+       allocate_child signal on GtkTextLayout
+
+       * gtk/gtktextiter.c (gtk_text_iter_get_pixbuf): fix bogus return
+       values
+       (gtk_text_iter_get_child_anchor): new function
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_real_changed): Add a
+       default handler for the changed signal, which calls
+       gtk_text_buffer_set_modified(), instead of just always emitting
+       changed then calling set_modified() manually. I guess this is
+       maybe more flexible. It seems logical.
+
 Fri Nov  3 08:58:38 2000  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkobject.c: _g_signal_handlers_destroy() is prefixed with '_'
index 3b8624549d76be220d129611cb71bc48d4319954..5e01c765e4f8a24352f7dd3c4aa2719f4a4907b5 100644 (file)
@@ -56,6 +56,7 @@ VOID:INT,INT,POINTER
 VOID:OBJECT
 VOID:OBJECT,BOXED,BOXED
 VOID:OBJECT,BOOLEAN
+VOID:OBJECT,INT,INT
 VOID:ENUM,INT
 VOID:POINTER
 VOID:POINTER,BOOLEAN
index 3b8624549d76be220d129611cb71bc48d4319954..5e01c765e4f8a24352f7dd3c4aa2719f4a4907b5 100644 (file)
@@ -56,6 +56,7 @@ VOID:INT,INT,POINTER
 VOID:OBJECT
 VOID:OBJECT,BOXED,BOXED
 VOID:OBJECT,BOOLEAN
+VOID:OBJECT,INT,INT
 VOID:ENUM,INT
 VOID:POINTER
 VOID:POINTER,BOOLEAN
index 3f0f7c2c2ef7e37ea05310cea3e456e0cddf2450..b73ba456c6124f963f4dfd2a45f49c9d849e0d1b 100644 (file)
@@ -195,6 +195,8 @@ struct _GtkTextBTree {
   GtkTextLine *end_iter_line;
 
   guint end_iter_line_stamp;
+
+  GHashTable *child_anchor_table;
 };
 
 
@@ -417,7 +419,8 @@ gtk_text_btree_new (GtkTextTagTable *table,
                                                   tree);
 
   tree->mark_table = g_hash_table_new (g_str_hash, g_str_equal);
-
+  tree->child_anchor_table = NULL;
+  
   /* We don't ref the buffer, since the buffer owns us;
    * we'd have some circularity issues. The buffer always
    * lasts longer than the BTree
@@ -1053,11 +1056,11 @@ gtk_text_btree_insert (GtkTextIter *iter,
   }
 }
 
-void
-gtk_text_btree_insert_pixbuf (GtkTextIter *iter,
-                              GdkPixbuf   *pixbuf)
+static void
+insert_pixbuf_or_widget_segment (GtkTextIter        *iter,
+                                 GtkTextLineSegment *seg)
+
 {
-  GtkTextLineSegment *seg;
   GtkTextIter start;
   GtkTextLineSegment *prevPtr;
   GtkTextLine *line;
@@ -1068,8 +1071,6 @@ gtk_text_btree_insert_pixbuf (GtkTextIter *iter,
   tree = gtk_text_iter_get_btree (iter);
   start_byte_offset = gtk_text_iter_get_line_index (iter);
 
-  seg = _gtk_pixbuf_segment_new (pixbuf);
-
   prevPtr = gtk_text_line_segment_split (iter);
   if (prevPtr == NULL)
     {
@@ -1092,11 +1093,54 @@ gtk_text_btree_insert_pixbuf (GtkTextIter *iter,
   gtk_text_btree_get_iter_at_line (tree, &start, line, start_byte_offset);
 
   *iter = start;
-  gtk_text_iter_next_char (iter); /* skip forward past the pixmap */
+  gtk_text_iter_next_char (iter); /* skip forward past the segment */
 
   gtk_text_btree_invalidate_region (tree, &start, iter);
 }
+     
+void
+gtk_text_btree_insert_pixbuf (GtkTextIter *iter,
+                              GdkPixbuf   *pixbuf)
+{
+  GtkTextLineSegment *seg;
+  
+  seg = _gtk_pixbuf_segment_new (pixbuf);
+
+  insert_pixbuf_or_widget_segment (iter, seg);
+}
+
+GtkTextChildAnchor*
+gtk_text_btree_create_child_anchor (GtkTextIter *iter)
+{
+  GtkTextLineSegment *seg;
+  GtkTextBTree *tree;
+  
+  seg = _gtk_widget_segment_new ();
+
+  insert_pixbuf_or_widget_segment (iter, seg);
+
+  tree = seg->body.child.tree;
+
+  if (tree->child_anchor_table == NULL)
+    tree->child_anchor_table = g_hash_table_new (NULL, NULL);
+
+  g_hash_table_insert (tree->child_anchor_table,
+                       seg->body.child.obj,
+                       seg->body.child.obj);
+  
+  return seg->body.child.obj;
+}
+
+void
+gtk_text_btree_unregister_child_anchor (GtkTextChildAnchor *anchor)
+{
+  GtkTextLineSegment *seg;
 
+  seg = anchor->segment;
+  
+  g_hash_table_remove (seg->body.child.tree->child_anchor_table,
+                       anchor);
+}
 
 /*
  * View stuff
@@ -2069,7 +2113,8 @@ copy_segment (GString *string,
 
       /* printf ("  :%s\n", string->str); */
     }
-  else if (seg->type == &gtk_text_pixbuf_type)
+  else if (seg->type == &gtk_text_pixbuf_type ||
+           seg->type == &gtk_text_child_type)
     {
       gboolean copy = TRUE;
 
index f5ce91d159d4fa2a1151b6df3c435779a38ed295..a2229373ce46c9a8b424df7d1b43dbd449ae11b9 100644 (file)
@@ -34,7 +34,9 @@ void gtk_text_btree_insert        (GtkTextIter *iter,
 void gtk_text_btree_insert_pixbuf (GtkTextIter *iter,
                                    GdkPixbuf   *pixbuf);
 
+GtkTextChildAnchor* gtk_text_btree_create_child_anchor (GtkTextIter *iter);
 
+void gtk_text_btree_unregister_child_anchor (GtkTextChildAnchor *anchor);
 
 /* View stuff */
 GtkTextLine *gtk_text_btree_find_line_by_y    (GtkTextBTree      *tree,
@@ -129,6 +131,11 @@ gboolean gtk_text_btree_get_iter_at_last_toggle  (GtkTextBTree       *tree,
                                                   GtkTextIter        *iter,
                                                   GtkTextTag         *tag);
 
+void     gtk_text_btree_get_iter_at_child_anchor  (GtkTextBTree       *tree,
+                                                   GtkTextIter        *iter,
+                                                   GtkTextChildAnchor *anchor);
+
+
 
 /* Manipulate marks */
 GtkTextMark        *gtk_text_btree_set_mark                (GtkTextBTree       *tree,
index 0c3ded39c3191c82adcc380af99a30ade04f3dee..c3fcf25e171cdf36e4cba20b23a3250aa9fb5578 100644 (file)
@@ -93,6 +93,7 @@ static void gtk_text_buffer_real_remove_tag            (GtkTextBuffer     *buffe
                                                         GtkTextTag        *tag,
                                                         const GtkTextIter *start_char,
                                                         const GtkTextIter *end_char);
+static void gtk_text_buffer_real_changed               (GtkTextBuffer     *buffer);
 
 static GtkTextBTree* get_btree (GtkTextBuffer *buffer);
 
@@ -230,6 +231,7 @@ gtk_text_buffer_class_init (GtkTextBufferClass *klass)
   klass->delete_text = gtk_text_buffer_real_delete_text;
   klass->apply_tag = gtk_text_buffer_real_apply_tag;
   klass->remove_tag = gtk_text_buffer_real_remove_tag;
+  klass->changed = gtk_text_buffer_real_changed;
 }
 
 void
@@ -401,8 +403,6 @@ gtk_text_buffer_real_insert_text (GtkTextBuffer *buffer,
   gtk_text_btree_insert (iter, text, len);
 
   gtk_signal_emit (GTK_OBJECT (buffer), signals[CHANGED]);
-
-  gtk_text_buffer_set_modified (buffer, TRUE);
 }
 
 static void
@@ -738,8 +738,6 @@ gtk_text_buffer_real_delete_text (GtkTextBuffer *buffer,
   gtk_text_buffer_update_primary_selection (buffer);
 
   gtk_signal_emit (GTK_OBJECT (buffer), signals[CHANGED]);
-
-  gtk_text_buffer_set_modified (buffer, TRUE);
 }
 
 static void
@@ -1021,10 +1019,31 @@ gtk_text_buffer_insert_pixbuf         (GtkTextBuffer      *buffer,
   /* FIXME pixbuf-specific signal like insert_text */
 
   gtk_signal_emit (GTK_OBJECT (buffer), signals[CHANGED]);
+}
 
-  gtk_text_buffer_set_modified (buffer, TRUE);
+/*
+ * Child anchor
+ */
+
+GtkTextChildAnchor*
+gtk_text_buffer_create_child_anchor (GtkTextBuffer *buffer,
+                                     GtkTextIter   *iter)
+{
+  GtkTextChildAnchor *anchor;
+  
+  g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
+  g_return_val_if_fail (iter != NULL, NULL);
+
+  anchor = gtk_text_btree_create_child_anchor (iter);
+
+  /* FIXME child-anchor-specific signal */
+  
+  gtk_signal_emit (GTK_OBJECT (buffer), signals[CHANGED]);
+
+  return anchor;
 }
 
+
 /*
  * Mark manipulation
  */
@@ -1350,41 +1369,19 @@ gtk_text_buffer_get_selection_bound (GtkTextBuffer *buffer)
   return gtk_text_buffer_get_mark (buffer, "selection_bound");
 }
 
-
-GtkTextChildAnchor*
-gtk_text_buffer_create_child_anchor (GtkTextBuffer      *buffer,
-                                     const GtkTextIter  *where)
-{
-  /* FIXME: Implement? */
-
-  return NULL;
-}
-
-void
-gtk_text_buffer_move_child_anchor (GtkTextBuffer      *buffer,
-                                   GtkTextChildAnchor *anchor,
-                                   GtkTextIter        *where)
-{
-
-
-}
-
-void
-gtk_text_buffer_delete_child_anchor (GtkTextBuffer      *buffer,
-                                     GtkTextChildAnchor *anchor)
-{
-
-
-
-}
-
 void
 gtk_text_buffer_get_iter_at_child_anchor (GtkTextBuffer      *buffer,
                                           GtkTextIter        *iter,
                                           GtkTextChildAnchor *anchor)
 {
-
-
+  g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
+  g_return_if_fail (iter != NULL);
+  g_return_if_fail (GTK_IS_TEXT_CHILD_ANCHOR (anchor));
+  g_return_if_fail (!gtk_text_child_anchor_get_deleted (anchor));
+  
+  gtk_text_btree_get_iter_at_child_anchor (get_btree (buffer),
+                                           iter,
+                                           anchor);
 }
 
 /**
@@ -1473,6 +1470,11 @@ gtk_text_buffer_real_remove_tag (GtkTextBuffer *buffer,
   gtk_text_btree_tag (start, end, tag, FALSE);
 }
 
+static void
+gtk_text_buffer_real_changed (GtkTextBuffer *buffer)
+{
+  gtk_text_buffer_set_modified (buffer, TRUE);
+}
 
 static void
 gtk_text_buffer_emit_tag (GtkTextBuffer *buffer,
index 2b60ab56e704fabc161018aa5232b957756bccb7..c1b5fcdd58ed87b9529bd4da382b0de5c67ba465 100644 (file)
@@ -78,8 +78,9 @@ struct _GtkTextBufferClass {
                             GtkTextIter *end,
                             gboolean interactive);
 
-  /* Only for text changed, marks/tags don't cause this
-     to be emitted */
+  /* Only for text/widgets/pixbuf changed, marks/tags don't cause this
+   * to be emitted
+   */
   void (* changed)         (GtkTextBuffer *buffer);
 
 
@@ -193,6 +194,10 @@ void gtk_text_buffer_insert_pixbuf         (GtkTextBuffer *buffer,
                                             GtkTextIter   *iter,
                                             GdkPixbuf     *pixbuf);
 
+/* Create a child anchor */
+GtkTextChildAnchor *gtk_text_buffer_create_child_anchor (GtkTextBuffer *buffer,
+                                                         GtkTextIter   *iter);
+
 /* Mark manipulation */
 GtkTextMark   *gtk_text_buffer_create_mark (GtkTextBuffer     *buffer,
                                             const gchar       *mark_name,
@@ -215,17 +220,6 @@ void gtk_text_buffer_delete_mark_by_name (GtkTextBuffer     *buffer,
 GtkTextMark* gtk_text_buffer_get_insert          (GtkTextBuffer *buffer);
 GtkTextMark* gtk_text_buffer_get_selection_bound (GtkTextBuffer *buffer);
 
-/* Child widget anchors */
-
-GtkTextChildAnchor* gtk_text_buffer_create_child_anchor (GtkTextBuffer      *buffer,
-                                                         const GtkTextIter  *where);
-void                gtk_text_buffer_move_child_anchor   (GtkTextBuffer      *buffer,
-                                                         GtkTextChildAnchor *anchor,
-                                                         GtkTextIter        *where);
-void                gtk_text_buffer_delete_child_anchor (GtkTextBuffer      *buffer,
-                                                         GtkTextChildAnchor *anchor);
-
-
 /* efficiently move insert and selection_bound to same location */
 void gtk_text_buffer_place_cursor (GtkTextBuffer     *buffer,
                                    const GtkTextIter *where);
index 2baac103300d5c006a7d69da5d7d6f0cbed052b0..88c81267e8dbf12072c530f477722cb2eb0bd274 100644 (file)
@@ -49,6 +49,7 @@
 
 #include "gtktextchild.h"
 #include "gtktextbtree.h"
+#include "gtktextlayout.h"
 
 static GtkTextLineSegment *
 pixbuf_segment_cleanup_func (GtkTextLineSegment *seg,
@@ -137,8 +138,35 @@ child_segment_delete_func (GtkTextLineSegment *seg,
                            GtkTextLine       *line,
                            gboolean           tree_gone)
 {
-  _gtk_widget_segment_unref (seg);
+  GSList *tmp_list;
+  GSList *copy;
 
+  gtk_text_btree_unregister_child_anchor (seg->body.child.obj);
+  
+  seg->body.child.tree = NULL;
+  seg->body.child.line = NULL;
+
+  /* avoid removing widgets while walking the list */
+  copy = g_slist_copy (seg->body.child.widgets);
+  tmp_list = copy;
+  while (tmp_list != NULL)
+    {
+      GtkWidget *child = tmp_list->data;
+
+      gtk_widget_destroy (child);
+      
+      tmp_list = g_slist_next (tmp_list);
+    }
+
+  /* On removal from the widget's parents (GtkTextView),
+   * the widget should have been removed from the anchor.
+   */
+  g_assert (seg->body.child.widgets == NULL);
+
+  g_slist_free (copy);
+  
+  _gtk_widget_segment_unref (seg);  
+  
   return 0;
 }
 
@@ -185,7 +213,8 @@ _gtk_widget_segment_new (void)
                         */
   seg->char_count = 1;
 
-  seg->body.child.ref_count = 1;
+  seg->body.child.obj = g_object_new (GTK_TYPE_TEXT_CHILD_ANCHOR, NULL);
+  seg->body.child.obj->segment = seg;
   seg->body.child.widgets = NULL;
   seg->body.child.tree = NULL;
   seg->body.child.line = NULL;
@@ -197,21 +226,23 @@ void
 _gtk_widget_segment_add    (GtkTextLineSegment *widget_segment,
                             GtkWidget          *child)
 {
-  g_assert (widget_segment->type = &gtk_text_child_type);
+  g_return_if_fail (widget_segment->type = &gtk_text_child_type);
+  g_return_if_fail (widget_segment->body.child.tree != NULL);
 
+  g_object_ref (G_OBJECT (child));
+  
   widget_segment->body.child.widgets =
     g_slist_prepend (widget_segment->body.child.widgets,
                      child);
-
-  g_object_ref (G_OBJECT (child));
 }
 
 void
 _gtk_widget_segment_remove (GtkTextLineSegment *widget_segment,
                             GtkWidget          *child)
 {
-  g_assert (widget_segment->type = &gtk_text_child_type);
-
+  g_return_if_fail (widget_segment->type = &gtk_text_child_type);
+  g_return_if_fail (widget_segment->body.child.tree != NULL);
+  
   widget_segment->body.child.widgets =
     g_slist_remove (widget_segment->body.child.widgets,
                     child);
@@ -224,7 +255,7 @@ _gtk_widget_segment_ref (GtkTextLineSegment *widget_segment)
 {
   g_assert (widget_segment->type = &gtk_text_child_type);
 
-  widget_segment->body.child.ref_count += 1;
+  g_object_ref (G_OBJECT (widget_segment->body.child.obj));
 }
 
 void
@@ -232,55 +263,112 @@ _gtk_widget_segment_unref (GtkTextLineSegment *widget_segment)
 {
   g_assert (widget_segment->type = &gtk_text_child_type);
 
-  widget_segment->body.child.ref_count -= 1;
-
-  if (widget_segment->body.child.ref_count == 0)
-    {
-      GSList *tmp_list;
+  g_object_unref (G_OBJECT (widget_segment->body.child.obj));
+}
 
-      if (widget_segment->body.child.tree == NULL)
-        g_warning ("widget segment destroyed while still in btree");
+GtkTextLayout*
+_gtk_anchored_child_get_layout (GtkWidget *child)
+{
+  return gtk_object_get_data (GTK_OBJECT (child), "gtk-text-child-anchor-layout");  
+}
 
-      tmp_list = widget_segment->body.child.widgets;
-      while (tmp_list)
-        {
-          g_object_unref (G_OBJECT (tmp_list->data));
+static void
+_gtk_anchored_child_set_layout (GtkWidget     *child,
+                                GtkTextLayout *layout)
+{
+  gtk_object_set_data (GTK_OBJECT (child),
+                       "gtk-text-child-anchor-layout",
+                       layout);  
+}
+     
+static void gtk_text_child_anchor_init       (GtkTextChildAnchor      *child_anchor);
+static void gtk_text_child_anchor_class_init (GtkTextChildAnchorClass *klass);
+static void gtk_text_child_anchor_finalize   (GObject                 *obj);
 
-          tmp_list = g_slist_next (tmp_list);
-        }
+static gpointer parent_class = NULL;
 
-      g_slist_free (widget_segment->body.child.widgets);
+GType
+gtk_text_child_anchor_get_type (void)
+{
+  static GType object_type = 0;
 
-      g_free (widget_segment);
+  if (!object_type)
+    {
+      static const GTypeInfo object_info =
+      {
+        sizeof (GtkTextChildAnchorClass),
+        (GBaseInitFunc) NULL,
+        (GBaseFinalizeFunc) NULL,
+        (GClassInitFunc) gtk_text_child_anchor_class_init,
+        NULL,           /* class_finalize */
+        NULL,           /* class_data */
+        sizeof (GtkTextChildAnchor),
+        0,              /* n_preallocs */
+        (GInstanceInitFunc) gtk_text_child_anchor_init,
+      };
+
+      object_type = g_type_register_static (G_TYPE_OBJECT,
+                                            "GtkTextChildAnchor",
+                                            &object_info, 0);
     }
+
+  return object_type;
 }
 
-void
-gtk_text_child_anchor_ref (GtkTextChildAnchor *anchor)
+static void
+gtk_text_child_anchor_init (GtkTextChildAnchor *child_anchor)
 {
-  GtkTextLineSegment *seg = (GtkTextLineSegment *) anchor;
+  child_anchor->segment = NULL;
+}
 
-  g_return_if_fail (seg->type = &gtk_text_child_type);
-  g_return_if_fail (seg->body.child.ref_count > 0);
+static void
+gtk_text_child_anchor_class_init (GtkTextChildAnchorClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-  _gtk_widget_segment_ref (seg);
+  parent_class = g_type_class_peek_parent (klass);
+
+  object_class->finalize = gtk_text_child_anchor_finalize;
 }
 
-void
-gtk_text_child_anchor_unref (GtkTextChildAnchor *anchor)
+static void
+gtk_text_child_anchor_finalize (GObject *obj)
 {
-  GtkTextLineSegment *seg = (GtkTextLineSegment *) anchor;
+  GtkTextChildAnchor *anchor;
+  GSList *tmp_list;
+  GtkTextLineSegment *seg;
+  
+  anchor = GTK_TEXT_CHILD_ANCHOR (obj);
 
-  g_return_if_fail (seg->type = &gtk_text_child_type);
-  g_return_if_fail (seg->body.child.ref_count > 0);
+  seg = anchor->segment;
+  
+  if (seg->body.child.tree != NULL)
+    {
+      g_warning ("Someone removed a reference to a GtkTextChildAnchor "
+                 "they didn't own; the anchor is still in the text buffer "
+                 "and the refcount is 0.");
+      return;
+    }
+      
+  tmp_list = seg->body.child.widgets;
+  while (tmp_list)
+    {
+      g_object_unref (G_OBJECT (tmp_list->data));
+      
+      tmp_list = g_slist_next (tmp_list);
+    }
+  
+  g_slist_free (seg->body.child.widgets);
+  
+  g_free (seg);
 
-  _gtk_widget_segment_unref (seg);
+  anchor->segment = NULL;
 }
 
 GList*
 gtk_text_child_anchor_get_widgets (GtkTextChildAnchor *anchor)
 {
-  GtkTextLineSegment *seg = (GtkTextLineSegment *) anchor;
+  GtkTextLineSegment *seg = anchor->segment;
   GList *list = NULL;
   GSList *iter;
 
@@ -303,12 +391,63 @@ gtk_text_child_anchor_get_widgets (GtkTextChildAnchor *anchor)
 gboolean
 gtk_text_child_anchor_get_deleted (GtkTextChildAnchor *anchor)
 {
-  GtkTextLineSegment *seg = (GtkTextLineSegment *) anchor;
+  GtkTextLineSegment *seg = anchor->segment;
 
   g_return_val_if_fail (seg->type = &gtk_text_child_type, TRUE);
 
   return seg->body.child.tree == NULL;
 }
 
+void
+gtk_text_child_anchor_register_child (GtkTextChildAnchor *anchor,
+                                      GtkWidget          *child,
+                                      GtkTextLayout      *layout)
+{
+  g_return_if_fail (GTK_IS_TEXT_CHILD_ANCHOR (anchor));
+  g_return_if_fail (GTK_IS_WIDGET (child));
 
+  _gtk_anchored_child_set_layout (child, layout);
+  
+  _gtk_widget_segment_add (anchor->segment, child);
+
+  gtk_text_child_anchor_queue_resize (anchor, layout);
+}
+
+void
+gtk_text_child_anchor_unregister_child (GtkTextChildAnchor *anchor,
+                                        GtkWidget          *child)
+{
+  g_return_if_fail (GTK_IS_TEXT_CHILD_ANCHOR (anchor));
+  g_return_if_fail (GTK_IS_WIDGET (child));
+  g_return_if_fail (_gtk_anchored_child_get_layout (child) != NULL);
+  
+  gtk_text_child_anchor_queue_resize (anchor,
+                                      _gtk_anchored_child_get_layout (child));
+  
+  _gtk_anchored_child_set_layout (child, NULL);
+  
+  _gtk_widget_segment_remove (anchor->segment, child);
+}
+
+void
+gtk_text_child_anchor_queue_resize (GtkTextChildAnchor *anchor,
+                                    GtkTextLayout      *layout)
+{
+  GtkTextIter start;
+  GtkTextIter end;
+  GtkTextLineSegment *seg;
+  
+  g_return_if_fail (GTK_IS_TEXT_CHILD_ANCHOR (anchor));
+
+  seg = anchor->segment;
+
+  g_return_if_fail (seg->body.child.tree != NULL);
+  
+  gtk_text_buffer_get_iter_at_child_anchor (layout->buffer,
+                                            &start, anchor);
+  end = start;
+  gtk_text_iter_next_char (&end);
+  
+  gtk_text_layout_invalidate (layout, &start, &end);
+}
 
index 5c8dc591fb396f52fd4abebd4b7b5e1fa6295875..0b10c91ab0aef0e81b71960e0ae70cd373758968 100644 (file)
@@ -27,7 +27,7 @@
 #ifndef GTK_TEXT_CHILD_H
 #define GTK_TEXT_CHILD_H
 
-#include <glib.h>
+#include <glib-object.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -39,10 +39,31 @@ extern "C" {
  * views.
  */
 
-typedef struct _GtkTextChildAnchor GtkTextChildAnchor;
+typedef struct _GtkTextChildAnchor      GtkTextChildAnchor;
+typedef struct _GtkTextChildAnchorClass GtkTextChildAnchorClass;
+
+#define GTK_TYPE_TEXT_CHILD_ANCHOR              (gtk_text_child_anchor_get_type ())
+#define GTK_TEXT_CHILD_ANCHOR(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GTK_TYPE_TEXT_CHILD_ANCHOR, GtkTextChildAnchor))
+#define GTK_TEXT_CHILD_ANCHOR_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_TEXT_CHILD_ANCHOR, GtkTextChildAnchorClass))
+#define GTK_IS_TEXT_CHILD_ANCHOR(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GTK_TYPE_TEXT_CHILD_ANCHOR))
+#define GTK_IS_TEXT_CHILD_ANCHOR_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_TEXT_CHILD_ANCHOR))
+#define GTK_TEXT_CHILD_ANCHOR_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_TEXT_CHILD_ANCHOR, GtkTextChildAnchorClass))
+
+struct _GtkTextChildAnchor
+{
+  GObject parent_instance;
+
+  gpointer segment;
+};
+
+struct _GtkTextChildAnchorClass
+{
+  GObjectClass parent_class;
+
+};
+
+GType gtk_text_child_anchor_get_type (void) G_GNUC_CONST;
 
-void     gtk_text_child_anchor_ref         (GtkTextChildAnchor *anchor);
-void     gtk_text_child_anchor_unref       (GtkTextChildAnchor *anchor);
 GList*   gtk_text_child_anchor_get_widgets (GtkTextChildAnchor *anchor);
 gboolean gtk_text_child_anchor_get_deleted (GtkTextChildAnchor *anchor);
 
index 8c19f07c082e70c66c3c276b55082942184362c7..24bb908e4cee63d32619d8a040a823d77d2d6189 100644 (file)
@@ -69,19 +69,21 @@ typedef struct _GtkTextChildBody GtkTextChildBody;
 
 struct _GtkTextChildBody
 {
-  guint ref_count;
+  GtkTextChildAnchor *obj;
   GSList *widgets;
   GtkTextBTree *tree;
   GtkTextLine *line;
 };
 
-GtkTextLineSegment *_gtk_widget_segment_new    (void);
-void                _gtk_widget_segment_add    (GtkTextLineSegment *widget_segment,
-                                                GtkWidget          *child);
-void                _gtk_widget_segment_remove (GtkTextLineSegment *widget_segment,
-                                                GtkWidget          *child);
-void                _gtk_widget_segment_ref    (GtkTextLineSegment *widget_segment);
-void                _gtk_widget_segment_unref  (GtkTextLineSegment *widget_segment);
+GtkTextLineSegment *_gtk_widget_segment_new      (void);
+void                _gtk_widget_segment_add      (GtkTextLineSegment *widget_segment,
+                                                  GtkWidget          *child);
+void                _gtk_widget_segment_remove   (GtkTextLineSegment *widget_segment,
+                                                  GtkWidget          *child);
+void                _gtk_widget_segment_ref      (GtkTextLineSegment *widget_segment);
+void                _gtk_widget_segment_unref    (GtkTextLineSegment *widget_segment);
+
+GtkTextLayout*      _gtk_anchored_child_get_layout (GtkWidget *child);
 
 #ifdef __cplusplus
 }
index 3a103593efa58c5839657ea52b25a9954887195b..10fd95c5624d01fa277551b3f0480474494c8f3d 100644 (file)
@@ -185,7 +185,7 @@ static void
 render_layout_line (GdkDrawable        *drawable,
                     GtkTextRenderState *render_state,
                     PangoLayoutLine    *line,
-                    GSList            **pixbuf_pointer,
+                    GSList            **shaped_pointer,
                     int                 x,
                     int                 y,
                     gboolean            selected)
@@ -272,68 +272,99 @@ render_layout_line (GdkDrawable        *drawable,
 
           x_off += logical_rect.width;
         }
-      else                      /* Pixbuf segment */
+      else                      /* Pixbuf or widget segment */
         {
-          GtkTextPixbuf *pixbuf = (*pixbuf_pointer)->data;
-          gint width, height;
-          GdkRectangle pixbuf_rect, draw_rect;
-          GdkBitmap *mask = NULL;
+          GObject *shaped = (*shaped_pointer)->data;
 
-          *pixbuf_pointer = (*pixbuf_pointer)->next;
-
-          width = gdk_pixbuf_get_width (pixbuf->pixbuf);
-          height = gdk_pixbuf_get_height (pixbuf->pixbuf);
-
-          pixbuf_rect.x = x + x_off / PANGO_SCALE;
-          pixbuf_rect.y = y - height;
-          pixbuf_rect.width = width;
-          pixbuf_rect.height = height;
-
-          if (gdk_rectangle_intersect (&pixbuf_rect, &render_state->clip_rect,
-                                       &draw_rect))
+          *shaped_pointer = (*shaped_pointer)->next;
+          
+          if (GDK_IS_PIXBUF (shaped))
             {
-              if (gdk_pixbuf_get_has_alpha (pixbuf->pixbuf))
+              gint width, height;
+              GdkRectangle pixbuf_rect, draw_rect;
+              GdkPixbuf *pixbuf;
+
+              pixbuf = GDK_PIXBUF (shaped);
+              
+              width = gdk_pixbuf_get_width (pixbuf);
+              height = gdk_pixbuf_get_height (pixbuf);
+
+              pixbuf_rect.x = x + x_off / PANGO_SCALE;
+              pixbuf_rect.y = y - height;
+              pixbuf_rect.width = width;
+              pixbuf_rect.height = height;
+
+              if (gdk_rectangle_intersect (&pixbuf_rect, &render_state->clip_rect,
+                                           &draw_rect))
                 {
-                  mask = gdk_pixmap_new (drawable,
-                                         gdk_pixbuf_get_width (pixbuf->pixbuf),
-                                         gdk_pixbuf_get_height (pixbuf->pixbuf),
-                                         1);
-
-                  gdk_pixbuf_render_threshold_alpha (pixbuf->pixbuf, mask,
-                                                     0, 0, 0, 0,
-                                                     gdk_pixbuf_get_width (pixbuf->pixbuf),
-                                                     gdk_pixbuf_get_height (pixbuf->pixbuf),
-                                                     128);
-
+                  GdkBitmap *mask = NULL;
+              
+                  if (gdk_pixbuf_get_has_alpha (pixbuf))
+                    {
+                      mask = gdk_pixmap_new (drawable,
+                                             gdk_pixbuf_get_width (pixbuf),
+                                             gdk_pixbuf_get_height (pixbuf),
+                                             1);
+
+                      gdk_pixbuf_render_threshold_alpha (pixbuf, mask,
+                                                         0, 0, 0, 0,
+                                                         gdk_pixbuf_get_width (pixbuf),
+                                                         gdk_pixbuf_get_height (pixbuf),
+                                                         128);
+
+                    }
+
+                  if (mask)
+                    {
+                      gdk_gc_set_clip_mask (render_state->fg_gc, mask);
+                      gdk_gc_set_clip_origin (render_state->fg_gc,
+                                              pixbuf_rect.x, pixbuf_rect.y);
+                    }
+
+                  gdk_pixbuf_render_to_drawable (pixbuf,
+                                                 drawable,
+                                                 render_state->fg_gc,
+                                                 draw_rect.x - pixbuf_rect.x,
+                                                 draw_rect.y - pixbuf_rect.y,
+                                                 draw_rect.x, draw_rect.y,
+                                                 draw_rect.width,
+                                                 draw_rect.height,
+                                                 GDK_RGB_DITHER_NORMAL,
+                                                 0, 0);
+
+                  if (mask)
+                    {
+                      gdk_gc_set_clip_rectangle (render_state->fg_gc,
+                                                 &render_state->clip_rect);
+                      g_object_unref (G_OBJECT (mask));
+                    }
                 }
 
-              if (mask)
+              x_off += width * PANGO_SCALE;
+            }
+          else if (GTK_IS_WIDGET (shaped))
+            {
+              gint width, height;
+              GdkRectangle draw_rect;
+              GtkWidget *widget;
+
+              widget = GTK_WIDGET (shaped);
+              
+              width = widget->allocation.width;
+              height = widget->allocation.height;
+
+              if (GTK_WIDGET_DRAWABLE (widget) &&
+                  gtk_widget_intersect (widget,
+                                        &render_state->clip_rect,
+                                        &draw_rect))
                 {
-                  gdk_gc_set_clip_mask (render_state->fg_gc, mask);
-                  gdk_gc_set_clip_origin (render_state->fg_gc,
-                                          pixbuf_rect.x, pixbuf_rect.y);
+                  gtk_widget_draw (widget, &draw_rect);
                 }
 
-              gdk_pixbuf_render_to_drawable (pixbuf->pixbuf,
-                                             drawable,
-                                             render_state->fg_gc,
-                                             draw_rect.x - pixbuf_rect.x,
-                                             draw_rect.y - pixbuf_rect.y,
-                                             draw_rect.x, draw_rect.y,
-                                             draw_rect.width,
-                                             draw_rect.height,
-                                             GDK_RGB_DITHER_NORMAL,
-                                             0, 0);
-
-              if (mask)
-                {
-                  gdk_gc_set_clip_rectangle (render_state->fg_gc,
-                                             &render_state->clip_rect);
-                  g_object_unref (G_OBJECT (mask));
-                }
+              x_off += width * PANGO_SCALE;
             }
-
-          x_off += width * PANGO_SCALE;
+          else
+            g_assert_not_reached (); /* not a pixbuf or widget */
         }
     }
 }
@@ -348,7 +379,7 @@ render_para (GdkDrawable        *drawable,
              int                 selection_end_index)
 {
   PangoRectangle logical_rect;
-  GSList *pixbuf_pointer = line_display->pixbufs;
+  GSList *shaped_pointer = line_display->shaped_objects;
   GSList *tmp_list;
   PangoAlignment align;
   PangoLayout *layout = line_display->layout;
@@ -431,15 +462,15 @@ render_para (GdkDrawable        *drawable,
                               TRUE,
                               x + line_display->left_margin, selection_y,
                               total_width / PANGO_SCALE, selection_height);
-          render_layout_line (drawable, render_state, line, &pixbuf_pointer,
+          render_layout_line (drawable, render_state, line, &shaped_pointer,
                               x + x_offset / PANGO_SCALE, y + (y_offset - logical_rect.y) / PANGO_SCALE,
                               TRUE);
         }
       else
         {
-          GSList *pixbuf_pointer_tmp = pixbuf_pointer;
+          GSList *shaped_pointer_tmp = shaped_pointer;
 
-          render_layout_line (drawable, render_state, line, &pixbuf_pointer,
+          render_layout_line (drawable, render_state, line, &shaped_pointer,
                               x + x_offset / PANGO_SCALE, y + (y_offset - logical_rect.y) / PANGO_SCALE,
                               FALSE);
 
@@ -461,7 +492,7 @@ render_para (GdkDrawable        *drawable,
                                   logical_rect.width / PANGO_SCALE,
                                   selection_height);
 
-              render_layout_line (drawable, render_state, line, &pixbuf_pointer_tmp,
+              render_layout_line (drawable, render_state, line, &shaped_pointer_tmp,
                                   x + x_offset / PANGO_SCALE, y + (y_offset - logical_rect.y) / PANGO_SCALE,
                                   TRUE);
 
index 4e5ba2bce846ec72546af94c2647b572d5069e21..e57855551af987671786a97a54069fdd8c9bc861 100644 (file)
@@ -849,21 +849,51 @@ gtk_text_iter_get_pixbuf (const GtkTextIter *iter)
 {
   GtkTextRealIter *real;
 
-  g_return_val_if_fail (iter != NULL, FALSE);
+  g_return_val_if_fail (iter != NULL, NULL);
 
   real = gtk_text_iter_make_real (iter);
 
   if (real == NULL)
-    return FALSE;
+    return NULL;
 
   check_invariants (iter);
 
   if (real->segment->type != &gtk_text_pixbuf_type)
-    return FALSE;
+    return NULL;
   else
     return real->segment->body.pixbuf.pixbuf;
 }
 
+/**
+ * gtk_text_iter_get_child_anchor:
+ * @iter: an iterator
+ *
+ * If the location pointed to by @iter contains a child anchor, the
+ * anchor is returned (with no new reference count added). Otherwise,
+ * NULL is returned.
+ *
+ * Return value: the anchor at @iter
+ **/
+GtkTextChildAnchor*
+gtk_text_iter_get_child_anchor (const GtkTextIter *iter)
+{
+  GtkTextRealIter *real;
+
+  g_return_val_if_fail (iter != NULL, NULL);
+
+  real = gtk_text_iter_make_real (iter);
+
+  if (real == NULL)
+    return NULL;
+
+  check_invariants (iter);
+
+  if (real->segment->type != &gtk_text_child_type)
+    return NULL;
+  else
+    return real->segment->body.child.obj;
+}
+
 /**
  * gtk_text_iter_get_marks:
  * @iter: an iterator
@@ -3733,6 +3763,25 @@ gtk_text_btree_get_iter_at_mark (GtkTextBTree *tree,
   check_invariants (iter);
 }
 
+void
+gtk_text_btree_get_iter_at_child_anchor (GtkTextBTree       *tree,
+                                         GtkTextIter        *iter,
+                                         GtkTextChildAnchor *anchor)
+{
+  GtkTextLineSegment *seg;
+
+  g_return_if_fail (iter != NULL);
+  g_return_if_fail (tree != NULL);
+  g_return_if_fail (GTK_IS_TEXT_CHILD_ANCHOR (anchor));
+
+  seg = anchor->segment;
+  
+  iter_init_from_segment (iter, tree,
+                          seg->body.child.line, seg);
+  g_assert (seg->body.child.line == gtk_text_iter_get_text_line (iter));
+  check_invariants (iter);
+}
+
 void
 gtk_text_btree_get_last_iter         (GtkTextBTree   *tree,
                                       GtkTextIter    *iter)
index 148046cfae874839adb68523b5a95369a5d2917a..3e649d0b40b34c36e3c88cb06d2f4321d6ae5e68 100644 (file)
@@ -28,6 +28,7 @@
 #define GTK_TEXT_ITER_H
 
 #include <gtk/gtktexttag.h>
+#include <gtk/gtktextchild.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -100,6 +101,8 @@ gchar   *gtk_text_iter_get_visible_text  (const GtkTextIter  *start,
 GdkPixbuf* gtk_text_iter_get_pixbuf (const GtkTextIter *iter);
 GSList  *  gtk_text_iter_get_marks  (const GtkTextIter *iter);
 
+GtkTextChildAnchor* gtk_text_iter_get_child_anchor (const GtkTextIter *iter);
+
 /* Return list of tags toggled at this point (toggled_on determines
    whether the list is of on-toggles or off-toggles) */
 GSList  *gtk_text_iter_get_toggled_tags  (const GtkTextIter  *iter,
index 2d590af1a4f27a347936344f77cd8314a01da1b8..cba5557b31a9516ec32d4b91c1bbb9b834dd20eb 100644 (file)
@@ -115,6 +115,7 @@ static PangoAttribute *gtk_text_attr_appearance_new (const GtkTextAppearance *ap
 enum {
   INVALIDATED,
   CHANGED,
+  ALLOCATE_CHILD,
   LAST_SIGNAL
 };
 
@@ -188,6 +189,18 @@ gtk_text_layout_class_init (GtkTextLayoutClass *klass)
                     GTK_TYPE_INT,
                     GTK_TYPE_INT);
 
+  signals[ALLOCATE_CHILD] =
+    gtk_signal_new ("allocate_child",
+                    GTK_RUN_LAST,
+                    GTK_CLASS_TYPE (object_class),
+                    GTK_SIGNAL_OFFSET (GtkTextLayoutClass, allocate_child),
+                    gtk_marshal_VOID__OBJECT_INT_INT,
+                    GTK_TYPE_NONE,
+                    3,
+                    GTK_TYPE_OBJECT,
+                    GTK_TYPE_INT,
+                    GTK_TYPE_INT);
+  
   gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
 
   object_class->destroy = gtk_text_layout_destroy;
@@ -1195,7 +1208,7 @@ add_text_attrs (GtkTextLayout      *layout,
 static void
 add_pixbuf_attrs (GtkTextLayout      *layout,
                   GtkTextLineDisplay *display,
-                  GtkTextAttributes *style,
+                  GtkTextAttributes  *style,
                   GtkTextLineSegment *seg,
                   PangoAttrList      *attrs,
                   gint                start)
@@ -1218,7 +1231,70 @@ add_pixbuf_attrs (GtkTextLayout      *layout,
   attr->end_index = start + seg->byte_count;
   pango_attr_list_insert (attrs, attr);
 
-  display->pixbufs = g_slist_append (display->pixbufs, pixbuf);
+  display->shaped_objects =
+    g_slist_append (display->shaped_objects, pixbuf->pixbuf);
+}
+
+static void
+add_child_attrs (GtkTextLayout      *layout,
+                 GtkTextLineDisplay *display,
+                 GtkTextAttributes  *style,
+                 GtkTextLineSegment *seg,
+                 PangoAttrList      *attrs,
+                 gint                start)
+{
+  PangoAttribute *attr;
+  PangoRectangle logical_rect;
+  GtkTextChildAnchor *anchor;
+  gint width, height;
+  GSList *tmp_list;
+
+  width = 1;
+  height = 1;
+  
+  anchor = seg->body.child.obj;
+
+  tmp_list = seg->body.child.widgets;
+  while (tmp_list != NULL)
+    {
+      GtkWidget *child = tmp_list->data;
+
+      if (_gtk_anchored_child_get_layout (child) == layout)
+        {
+          /* Found it */
+          GtkRequisition req;
+
+          gtk_widget_get_child_requisition (child, &req);
+          
+          width = req.width;
+          height = req.height;
+
+          display->shaped_objects =
+            g_slist_append (display->shaped_objects, child);                           
+          break;
+        }
+      
+      tmp_list = g_slist_next (tmp_list);
+    }
+
+  if (tmp_list == NULL)
+    {
+      /* No widget at this anchor in this display;
+       * not an error.
+       */
+
+      return;
+    }
+  
+  logical_rect.x = 0;
+  logical_rect.y = -height * PANGO_SCALE;
+  logical_rect.width = width * PANGO_SCALE;
+  logical_rect.height = height * PANGO_SCALE;
+
+  attr = pango_attr_shape_new (&logical_rect, &logical_rect);
+  attr->start_index = start;
+  attr->end_index = start + seg->byte_count;
+  pango_attr_list_insert (attrs, attr);
 }
 
 static void
@@ -1266,6 +1342,19 @@ add_cursor (GtkTextLayout      *layout,
     }
 }
 
+static void
+allocate_child_widgets (GtkTextLayout      *layout,
+                        GtkTextLineDisplay *display)
+{
+  
+#if 0
+  gtk_signal_emit (GTK_OBJECT (layout),
+                   signals[ALLOCATE_CHILD],
+                   child,
+                   x, y);
+#endif
+}
+
 GtkTextLineDisplay *
 gtk_text_layout_get_line_display (GtkTextLayout *layout,
                                   GtkTextLine   *line,
@@ -1329,7 +1418,8 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
     {
       /* Displayable segments */
       if (seg->type == &gtk_text_char_type ||
-          seg->type == &gtk_text_pixbuf_type)
+          seg->type == &gtk_text_pixbuf_type ||
+          seg->type == &gtk_text_child_type)
         {
           gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer),
                                            &iter, line,
@@ -1391,7 +1481,7 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
                   add_text_attrs (layout, style, byte_count, attrs,
                                   byte_offset - byte_count, size_only);
                 }
-              else
+              else if (seg->type == &gtk_text_pixbuf_type)
                 {
                   add_pixbuf_attrs (layout, display, style,
                                     seg, attrs, byte_offset);
@@ -1399,6 +1489,18 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
                           seg->byte_count);
                   byte_offset += seg->byte_count;
                 }
+              else if (seg->type == &gtk_text_child_type)
+                {
+                  add_child_attrs (layout, display, style,
+                                   seg, attrs, byte_offset);
+                  memcpy (text + byte_offset, gtk_text_unknown_char_utf8,
+                          seg->byte_count);
+                  byte_offset += seg->byte_count;
+                }
+              else
+                {
+                  g_assert_not_reached ();
+                }
             }
 
           release_style (layout, style);
@@ -1476,6 +1578,8 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
 
   layout->one_display_cache = display;
 
+  allocate_child_widgets (layout, display);
+  
   return display;
 }
 
@@ -1491,7 +1595,7 @@ gtk_text_layout_free_line_display (GtkTextLayout      *layout,
         {
           g_slist_foreach (display->cursors, (GFunc)g_free, NULL);
           g_slist_free (display->cursors);
-          g_slist_free (display->pixbufs);
+          g_slist_free (display->shaped_objects);
         }
 
       g_free (display);
index a4eb5858fb985aa2bd03f20acf956a8d5f6e9910..04ae9c0c772449c38e150d3441e796c698162696 100644 (file)
@@ -153,7 +153,7 @@ struct _GtkTextLayout
 
   /* Whether we are allowed to wrap right now */
   gint wrap_loop_count;
-
+  
   /* Whether to show the insertion cursor */
   guint cursor_visible : 1;
 };
@@ -185,7 +185,13 @@ struct _GtkTextLayoutClass
   void  (*free_line_data)       (GtkTextLayout     *layout,
                                  GtkTextLine       *line,
                                  GtkTextLineData   *line_data);
+
+  void (*allocate_child)        (GtkTextLayout     *layout,
+                                 GtkWidget         *child,
+                                 gint               x,
+                                 gint               y);
 };
+
 struct _GtkTextAttrAppearance
 {
   PangoAttribute attr;
@@ -203,8 +209,8 @@ struct _GtkTextLineDisplay
 {
   PangoLayout *layout;
   GSList *cursors;
-  GSList *pixbufs;
-
+  GSList *shaped_objects;
+  
   GtkTextDirection direction;
 
   gint width;                   /* Width of layout */
@@ -334,9 +340,22 @@ void gtk_text_layout_move_iter_visually         (GtkTextLayout *layout,
                                                  GtkTextIter   *iter,
                                                  gint           count);
 
-void gtk_text_layout_spew (GtkTextLayout *layout);
 
+/* Don't use these. Use gtk_text_view_add_child_at_anchor().
+ * These functions are defined in gtktextchild.c, but here
+ * since they are semi-public and require GtkTextLayout to
+ * be declared.
+ */
+void gtk_text_child_anchor_register_child   (GtkTextChildAnchor *anchor,
+                                             GtkWidget          *child,
+                                             GtkTextLayout      *layout);
+void gtk_text_child_anchor_unregister_child (GtkTextChildAnchor *anchor,
+                                             GtkWidget          *child);
+
+void gtk_text_child_anchor_queue_resize     (GtkTextChildAnchor *anchor,
+                                             GtkTextLayout      *layout);
 
+void gtk_text_layout_spew (GtkTextLayout *layout);
 
 #ifdef __cplusplus
 }
index 3f6c934fa52446211cd601a95c0f9cbabf570923..db43d8d36b17e5b93cbd6353484c747203bf7da6 100644 (file)
@@ -35,7 +35,6 @@
 #include "gtktextview.h"
 #include "gtkimmulticontext.h"
 #include "gdk/gdkkeysyms.h"
-#include "gtktexttypes.h"
 #include <string.h>
 
 #define FOCUS_EDGE_WIDTH 1
@@ -235,7 +234,8 @@ struct _GtkTextViewChild
 };
 
 static GtkTextViewChild* text_view_child_new_anchored (GtkWidget          *child,
-                                                       GtkTextChildAnchor *anchor);
+                                                       GtkTextChildAnchor *anchor,
+                                                       GtkTextLayout      *layout);
 static GtkTextViewChild* text_view_child_new_window   (GtkWidget          *child,
                                                        GtkTextWindowType   type,
                                                        gint                x,
@@ -244,7 +244,6 @@ static void              text_view_child_free         (GtkTextViewChild   *child
 
 static void              text_view_child_realize      (GtkTextView      *text_view,
                                                        GtkTextViewChild *child);
-static void              text_view_child_unrealize    (GtkTextViewChild *child);
 
 struct _GtkTextWindow
 {
@@ -278,7 +277,8 @@ static void           text_window_get_allocation  (GtkTextWindow     *win,
                                                    GdkRectangle      *rect);
 
 
-enum {
+enum
+{
   TARGET_STRING,
   TARGET_TEXT,
   TARGET_COMPOUND_TEXT,
@@ -708,7 +708,7 @@ gtk_text_view_new_with_buffer (GtkTextBuffer *buffer)
 }
 
 void
-gtk_text_view_set_buffer (GtkTextView *text_view,
+gtk_text_view_set_buffer (GtkTextView   *text_view,
                           GtkTextBuffer *buffer)
 {
   g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
@@ -719,6 +719,27 @@ gtk_text_view_set_buffer (GtkTextView *text_view,
 
   if (text_view->buffer != NULL)
     {
+      /* Destroy all anchored children */
+      GSList *tmp_list;
+      GSList *copy;
+      
+      copy = g_slist_copy (text_view->children);
+      tmp_list = copy;
+      while (tmp_list != NULL)
+        {
+          GtkTextViewChild *vc = tmp_list->data;
+
+          if (vc->anchor)
+            {
+              gtk_widget_destroy (vc->widget);
+              /* vc may now be invalid! */
+            }
+            
+          tmp_list = g_slist_next (tmp_list);
+        }
+
+      g_slist_free (copy);
+      
       gtk_signal_disconnect_by_func (GTK_OBJECT (text_view->buffer),
                                      gtk_text_view_mark_set_handler, text_view);
       gtk_object_unref (GTK_OBJECT (text_view->buffer));
@@ -1251,7 +1272,8 @@ gtk_text_view_size_request (GtkWidget      *widget,
                             GtkRequisition *requisition)
 {
   GtkTextView *text_view;
-
+  GSList *tmp_list;
+  
   text_view = GTK_TEXT_VIEW (widget);
 
   requisition->width = text_view->text_window->requisition.width + FOCUS_EDGE_WIDTH * 2;
@@ -1268,6 +1290,69 @@ gtk_text_view_size_request (GtkWidget      *widget,
 
   if (text_view->bottom_window)
     requisition->height += text_view->bottom_window->requisition.height;
+
+  tmp_list = text_view->children;
+  while (tmp_list != NULL)
+    {
+      GtkTextViewChild *child = tmp_list->data;
+
+      if (child->anchor)
+        {
+          GtkRequisition child_req;
+          GtkRequisition old_req;
+          
+          old_req = child->widget->requisition;
+
+          gtk_widget_size_request (child->widget, &child_req); 
+          
+          if (text_view->layout &&
+              (old_req.width != child_req.width ||
+               old_req.height != child_req.height))
+            gtk_text_child_anchor_queue_resize (child->anchor,
+                                                text_view->layout);
+        }
+      else
+        {
+
+        }
+          
+      tmp_list = g_slist_next (tmp_list);
+    }
+}
+
+static void
+gtk_text_view_allocate_children (GtkTextView *text_view)
+{
+  GSList *tmp_list;
+
+  return;
+  
+  tmp_list = text_view->children;
+  while (tmp_list != NULL)
+    {
+      GtkTextViewChild *child = tmp_list->data;
+
+      if (child->anchor)
+        {
+          /* We need to force-validate the regions containing
+           * children.
+           */
+          GtkTextIter child_loc;
+          gtk_text_buffer_get_iter_at_child_anchor (text_view->buffer,
+                                                    &child_loc,
+                                                    child->anchor);
+
+          gtk_text_layout_validate_yrange (text_view->layout,
+                                           &child_loc,
+                                           0, 1);
+        }
+      else
+        {
+          
+        }
+          
+      tmp_list = g_slist_next (tmp_list);
+    }
 }
 
 static void
@@ -1285,7 +1370,8 @@ gtk_text_view_size_allocate (GtkWidget *widget,
   GdkRectangle right_rect;
   GdkRectangle top_rect;
   GdkRectangle bottom_rect;
-
+  GSList *tmp_list;
+  
   text_view = GTK_TEXT_VIEW (widget);
 
   widget->allocation = *allocation;
@@ -1383,6 +1469,8 @@ gtk_text_view_size_allocate (GtkWidget *widget,
   gtk_text_layout_set_screen_width (text_view->layout,
                                     SCREEN_WIDTH (text_view));
 
+  gtk_text_view_allocate_children (text_view);
+  
   gtk_text_view_validate_onscreen (text_view);
   gtk_text_view_scroll_calc_now (text_view);
 
@@ -1603,7 +1691,7 @@ static void
 gtk_text_view_unrealize (GtkWidget *widget)
 {
   GtkTextView *text_view;
-
+  
   text_view = GTK_TEXT_VIEW (widget);
 
   if (text_view->first_validate_idle)
@@ -1617,7 +1705,7 @@ gtk_text_view_unrealize (GtkWidget *widget)
       g_source_remove (text_view->incremental_validate_idle);
       text_view->incremental_validate_idle = 0;
     }
-
+  
   text_window_unrealize (text_view->text_window);
 
   if (text_view->left_window)
@@ -2242,7 +2330,7 @@ gtk_text_view_remove (GtkContainer *container,
     }
 
   g_assert (iter != NULL); /* be sure we had the child in the list */
-
+  
   text_view->children = g_slist_remove (text_view->children, vc);
 
   gtk_widget_unparent (vc->widget);
@@ -4187,22 +4275,25 @@ gtk_text_view_set_text_window_size (GtkTextView *text_view,
 
 static GtkTextViewChild*
 text_view_child_new_anchored (GtkWidget          *child,
-                              GtkTextChildAnchor *anchor)
+                              GtkTextChildAnchor *anchor,
+                              GtkTextLayout      *layout)
 {
   GtkTextViewChild *vc;
-
+  
   vc = g_new (GtkTextViewChild, 1);
 
   vc->widget = child;
   vc->anchor = anchor;
 
   g_object_ref (G_OBJECT (vc->widget));
-  gtk_text_child_anchor_ref (vc->anchor);
+  g_object_ref (G_OBJECT (vc->anchor));
 
   gtk_object_set_data (GTK_OBJECT (child),
                        "gtk-text-view-child",
                        vc);
 
+  gtk_text_child_anchor_register_child (anchor, child, layout);
+  
   return vc;
 }
 
@@ -4235,9 +4326,15 @@ text_view_child_free (GtkTextViewChild *child)
   gtk_object_remove_data (GTK_OBJECT (child->widget),
                           "gtk-text-view-child");
 
-  g_object_unref (G_OBJECT (child->widget));
-  gtk_text_child_anchor_unref (child->anchor);
+  if (child->anchor)
+    {
+      gtk_text_child_anchor_unregister_child (child->anchor,
+                                              child->widget);
+      g_object_unref (G_OBJECT (child->anchor));
+    }
 
+  g_object_unref (G_OBJECT (child->widget));
+  
   g_free (child);
 }
 
@@ -4259,12 +4356,6 @@ text_view_child_realize (GtkTextView      *text_view,
   gtk_widget_realize (vc->widget);
 }
 
-static void
-text_view_child_unrealize (GtkTextViewChild *vc)
-{
-  gtk_widget_unrealize (vc->widget);
-}
-
 static void
 add_child (GtkTextView      *text_view,
            GtkTextViewChild *vc)
@@ -4295,10 +4386,13 @@ gtk_text_view_add_child_at_anchor (GtkTextView          *text_view,
 
   g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
   g_return_if_fail (GTK_IS_WIDGET (child));
-  g_return_if_fail (anchor != NULL);
+  g_return_if_fail (GTK_IS_TEXT_CHILD_ANCHOR (anchor));
   g_return_if_fail (child->parent == NULL);
 
-  vc = text_view_child_new_anchored (child, anchor);
+  gtk_text_view_ensure_layout (text_view);
+  
+  vc = text_view_child_new_anchored (child, anchor,
+                                     text_view->layout);
 
   add_child (text_view, vc);
 }